package geometria;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import modelo.TiempoInvalidoException;
import modelo.Velocidad;

/**
 * 
 * Esta clase representa un par ordenado en el plano.
 *
 */
public class Coordenada implements Comparable<Coordenada> {
	
	//public Double x;
	//public Double y;
	protected Point2D.Double p;
	
	public Coordenada(Double x, Double y) {
		this.p = new Point2D.Double(x, y);
	}
	
	public Coordenada() {
		this.p = new Point2D.Double();
	}
	
	public double getX(){
		return this.p.x;
	}
	
	public double getY(){
		return this.p.y;
	}
	public boolean coincideCon(Coordenada otra, Double tolerancia) {

		double dist = this.p.distance(otra.p);
		return ( dist <= tolerancia);

//		Coordenada resta = this.menos(otra);
//		Double norma = resta.getModulo();
//		return (norma <= tolerancia);
//		return  ( ( this.x.equals(otra.x) ) && ( this.y.equals(otra.y) ));
	}
	 
	public Coordenada menos(Coordenada otra) {
		return new Coordenada( this.getX() - otra.getX(), this.getY() - otra.getY());
//		Double xFinal = this.x - otra.x;
//		Double yFinal = this.y - otra.y;
//		
//		return new Coordenada(xFinal, yFinal);
	}
	 
	
	public Coordenada moverConVelocidad(Velocidad v, Double tiempo) {
		 /**
		  *  Permite obtener una coordenada que resulta de desplazar this con velocidad v durante el tiempo indicado.
		  */
		Double nuevax, nuevay;
		
		if (tiempo < 0) throw new TiempoInvalidoException();
		nuevax = this.p.x + (tiempo * v.getX());
		nuevay = this.p.y + (tiempo * v.getY());
		 
		return new Coordenada(nuevax, nuevay);
	}
	 
	public void normalizar() {
		 
		Double moduloAnterior = this.getModulo();
		 
		this.p.x = ( this.p.x )/ moduloAnterior;
		this.p.y = ( this.p.y )/ moduloAnterior;	 
	 }
	 
	 public double getModulo() {
			// Pitagoras
			//return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
		 	// El módulo de un vector es su distancia al origen de coordenadas
		 	return this.p.distance(0D, 0D);
	}
	 
	public Double getDistancia(Coordenada otra) {
		return this.p.distance(otra.p);
		//return (this.menos(otra).getModulo());	
	}
	 
/**
 * 
 * @param destino coordenada de destino
 * @param tiempo tiempo durante el cual me muevo
 * @param velocidad velocidad con la que me muevo
 * @return Devuelve un numero positivo si llegue al destino antes de que se acabe el tiempo, -1 en otro caso.
 */
	 
	
	 public void mover(Coordenada destino, Double tiempo, Double velocidad) {
		
		Double dx,dy;

		Coordenada direccion;
		
		direccion = destino.menos(this);
		direccion.normalizar();
		direccion.MultiplicarPor(velocidad);
			
		dx = direccion.getX() * tiempo;
		dy = direccion.getY() * tiempo;
		Coordenada nuevaCoordenadaPotencial = new Coordenada(this.getX() + dx, this.getY() + dy);

				
		// if ((r.intersects(destino.x,destino.y,1D,1D)) ||
		// destino.coincideCon(new Coordenada(nuevox,nuevoy), 1D) ){
		if (destino.estaEnElMedio(this, nuevaCoordenadaPotencial)) {
			// Nos pasamos!
			this.p = destino.p;
		} else {
			this.p = nuevaCoordenadaPotencial.p;
		}
}


public boolean estaEnElMedio(Coordenada c1, Coordenada c2){
	Line2D.Double laux = new Line2D.Double(c1.p, c2.p);
	Rectangle2D.Double raux = new Rectangle2D.Double(this.getX(),this.getY(),1D,1D); 
	return raux.intersectsLine(laux);
}



	@Override
	 public String toString() {
		return this.p.toString();
	 }
	 
		
		@Override
		public boolean equals(Object otra) {
			return this.coincideCon((Coordenada)otra,1D);
		}

		@Override
		public int compareTo(Coordenada otra) {
			if (this.coincideCon(otra,1D))
				return 0;
			return 1;
		}
		 private void MultiplicarPor(Double velocidad) {
			 this.p = new Point2D.Double( velocidad * this.getX() , velocidad * this.getY() );
		 }
	
}
